package gdt.service;

import javax.persistence.NoResultException;

import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import gdt.dao.CategoryDAO;
import gdt.entity.Category;
import gdt.entity.Project;
import gdt.service.utils.Validator;


public class CategoryService {

	@Transactional(readOnly=true)
	public Category findById(long id){
		return categoryDao.findById(id);
	}
	
	@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
	public boolean save(Category category, MessageContext messageContext){
		if(validate(category,messageContext)){
			if(category.getParent() != null)
				category.getParent().addCategory(category);
			else
				category.getParentProject().addCategory(category);
			save(category);
			return true;
		}
		else{
			return false;
		}
	}
	
	@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
	public void save(Category category){
		category = categoryDao.makePersistent(category);
	}
	
	@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
	public boolean delete(Category category, MessageContext messageContext){
		if(category.getChildren().isEmpty() && category.getTasks().isEmpty()){
			if(category.getParent() != null)
				category.getParent().removeCategory(category);
			else
				category.getParentProject().removeCategory(category);
			categoryDao.makeTransient(category);
			return true;
		}else{
			messageContext.addMessage((new MessageBuilder()).error().code("error_category_delete").build());
			return false;
		}
	}
	

	public Category setup(Project project){
		Category c = new Category();
		c.setParentProject(project);
		return c;
	}
	

	public Category setup(Category parentCategory){
		Category c = new Category();
		c.setParent(parentCategory);
		return c;
	}
	
	
	
	/********************************* DAO's *********************************/
	
	private CategoryDAO categoryDao;
	
	public void setCategoryDao(CategoryDAO categoryDao) {
		this.categoryDao = categoryDao;
	}


	/******************************* Validation *******************************/
	
	private Validator validator;
	
	public boolean validate(Category category, MessageContext context){
		boolean valid = validator.validate(category, context);
		
		Category categoryWithName = null;
		try{
			if(category.getParentProject() != null)
				categoryWithName = categoryDao.findByProjectAndName(category.getParentProject(), category.getName());
			else
				categoryWithName = categoryDao.findByCategoryAndName(category.getParent(), category.getName());
		}catch(NoResultException e){
			//The project name isn't registered yet, so we just do nothing
		}

		if((categoryWithName != null) && ((category.getId() == 0) || (categoryWithName.getId() != category.getId()))){
			context.addMessage((new MessageBuilder()).error().code("error_existing_projectname").build());
			valid = false;
		}
			
		return valid;
	}
	
	public Validator getValidator() {
		return validator;
	}

	public void setValidator(Validator validator) {
		this.validator = validator;
	}
	
}
